package cn.exlu.coco.core.server.sftp;

import java.io.File;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Map.Entry;

import cn.exlu.coco.core.exception.CoCoException;
import cn.exlu.coco.core.utils.DateUtil;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

/**
 * SFTP上传
 * 详细描述
 * 
 * @version 1.0.0
 * @author Mark
 * @see 参照者
 * @since 1.0.1.1
 * @date 2017年7月7日
 */
public class SFtpServer {

    private static Map<String, Session> map = new HashMap<String, Session>();
    private static Map<String, SftpAccount> accMap = new HashMap<String, SftpAccount>();

    private static JSch jsch = new JSch();
    
    private ChannelSftp channel;
    
    private String ftpRoot;
    
    public static void stop(){
        for(Entry<String, Session> val: map.entrySet()){
            Session sion = val.getValue();
            if(sion != null){
                sion .disconnect();
            }
        }
    }

    public SFtpServer(String addrIp) throws CoCoException{
        channel = getChannel(addrIp);
    }
    
    public static boolean checkIpAddr(String ipAddr){
        SftpAccount acc = getAccMap(ipAddr);
        if(acc == null){
            return false;
        }
        return true;
    }

    private static SftpAccount getAccMap(String addrIp){

        synchronized (accMap) {
            if(accMap.isEmpty()){
                SftpAccount acc1 = new SftpAccount("ip", "username", "password", -1, "root");
                accMap.put("107.191.52.134", acc1);
            }
        }

        return accMap.get(addrIp);
    }

    /**
     * 获取channel
     * @param addrIp
     * @return
     * @throws CoCoException
     */
    private ChannelSftp getChannel(String addrIp)  throws CoCoException{
        SftpAccount acc = getAccMap(addrIp);
        if(acc == null){
            return null;
        }
        Session jschSession = map.get(addrIp);
        try{
            if(jschSession == null || !jschSession.isConnected() ){
                jschSession = jsch.getSession(acc.getUserName(), acc.getAddrIp(), acc.getPort());
                jschSession.setPassword(acc.getUserPasswd());
                Hashtable<String,String> config = new Hashtable<String,String>();
                config.put("StrictHostKeyChecking", "no");
                jschSession.setConfig(config);
                jschSession.connect();
                
                channel = (ChannelSftp) jschSession.openChannel("sftp");
                channel.connect(1 * 60 * 1000);
                ftpRoot = acc.getFtpRoot();
                map.put(addrIp, jschSession);
                
                return channel;

            }

            channel = (ChannelSftp) jschSession.openChannel("sftp");
            // timeout 设置1分钟
            channel.connect(1 * 60 * 1000);
            ftpRoot = acc.getFtpRoot();

            return channel;

        }catch(Exception e){
            throw new CoCoException("打开链接失败。");
        }
    }

    /**
     * 关闭channel
     */
    public void close(){
        if(channel != null){
            channel.disconnect();
        }
    }

    /**
     * 将指定文件
     * @param file
     * @param serverDestDir
     * @throws CoCoException 
     */
    public void uploadFile(File file) throws CoCoException{
        try {
            channel.put(file.getAbsolutePath(), file.getName());
        } catch (SftpException e) {
            throw new CoCoException("上传失败", e);
        }

    }

    public void download(String srcPath, String desPath) throws CoCoException{
        try {
            channel.get(srcPath, desPath);
        } catch (SftpException e) {
            throw new CoCoException("下载失败:"+e.getMessage(), e);
        }
    }

    /**
     * 在根目录下创建新目录
     * @return
     * @throws CoCoException
     */
    public String createNewDir() throws CoCoException{
        String newDirName = DateUtil.currentDateTimestamp();
        try {
            channel.cd(ftpRoot);
            channel.mkdir(newDirName);
        } catch (SftpException e) {
            throw new CoCoException("创建新目录失败", e);
        }
        
        return newDirName;
    }

    public void cdDir(String dir) throws CoCoException{
        try {
            channel.cd(ftpRoot + "/" + dir);
        } catch (SftpException e) {
            throw new CoCoException("跳转目录失败", e);
        }
    }

    /**
     * 上传目录
     * @param dir
     * @throws CoCoException
     */
    public void uploadDir(File dir) throws CoCoException{
        // 先创建目录
        try {
            String curPwd = channel.pwd();
            
            channel.mkdir(dir.getName());
            
            String newPwd = curPwd + "/" + dir.getName();
            for(File file : dir.listFiles()){
                if(file.isFile()){
                    // 文件的场合
                    channel.cd(newPwd);
                    channel.put(file.getAbsolutePath(), file.getName());
                }else if(file.isDirectory()){
                    uploadDir(file);
                }
            }
        } catch (SftpException e) {
            throw new CoCoException("上传失败：", e);
        }

    }

    /**
     * 获取用户HOME目录
     * @return
     * @throws CoCoException
     */
    public String getFtpRoot(){
        return ftpRoot;
    }

}
